package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/therecipe/qt/gui"

	"github.com/rocket049/gettext-go/gettext"

	"github.com/therecipe/qt/core"
	"github.com/therecipe/qt/widgets"
)

func T(s string) string {
	return gettext.T(s)
}

type myWindow struct {
	app    *widgets.QApplication
	window *widgets.QDialog
	login  *widgets.QDialog
	header *widgets.QLabel
	board  *widgets.QTableView
	users  *widgets.QTableView
	input  *widgets.QLineEdit
	tray   *widgets.QSystemTrayIcon

	userModel *gui.QStandardItemModel
	msgModel  *gui.QStandardItemModel

	once sync.Once

	bridge *QmlBridge
}

func (s *myWindow) CreateWithApp(app *widgets.QApplication) {
	s.bridge = NewQmlBridge(nil)

	s.window = widgets.NewQDialog(nil, core.Qt__Window)
	s.window.SetWindowTitle(T("Security Chat by IRC"))
	s.window.SetFixedSize2(800, 600)

	grid := widgets.NewQGridLayout2()
	//main chat layout
	s.header = widgets.NewQLabel(s.window, core.Qt__Widget)
	grid.AddWidget3(s.header, 0, 0, 1, 2, 0)

	s.board = widgets.NewQTableView(s.window)

	grid.AddWidget(s.board, 1, 0, 0)
	s.board.SetEditTriggers(widgets.QAbstractItemView__NoEditTriggers)

	s.msgModel = gui.NewQStandardItemModel2(0, 2, s.board)
	s.board.SetColumnWidth(0, 120)
	s.board.SetColumnWidth(1, s.board.Viewport().Width()-120)
	s.board.SetAlternatingRowColors(true)
	s.board.SetModel(s.msgModel)

	s.msgModel.SetHorizontalHeaderLabels([]string{T("Sender"), T("Message")})

	s.users = widgets.NewQTableView(s.window)
	grid.AddWidget(s.users, 1, 1, 0)
	s.users.SetEditTriggers(widgets.QAbstractItemView__NoEditTriggers)
	s.users.SetFixedWidth(130)
	s.users.SetColumnWidth(0, 130)

	s.userModel = gui.NewQStandardItemModel2(0, 1, nil)

	s.userModel.SetHorizontalHeaderLabels([]string{T("Users")})
	s.users.SetModel(s.userModel)

	s.input = widgets.NewQLineEdit(s.window)
	grid.AddWidget3(s.input, 2, 0, 1, 2, 0)
	s.input.SetToolTip("input text here, send after RETURN.")

	s.input.ConnectEditingFinished(func() {
		msg := s.input.Text()
		if len(msg) > 0 {
			bot.PrivMsgTo(target, msg)
			s.input.SetText("")
			s.appendMsgColor(bot.Nick, msg, core.Qt__blue)
		}
	})

	s.setSignals()

	s.window.SetLayout(grid)
	app.SetActiveWindow(s.window)
}

func (s *myWindow) setTableColumnWidth() {
	s.once.Do(func() {
		s.board.SetColumnWidth(1, s.board.Width()-140)
		s.users.SetColumnWidth(0, s.users.Width())
	})
}

func (s *myWindow) appendMsgColor(sender, msg string, color core.Qt__GlobalColor) {
	h1 := gui.NewQStandardItem2(sender)

	h2 := gui.NewQStandardItem2(msg)

	h1.SetForeground(gui.NewQBrush3(gui.NewQColor2(color), core.Qt__NoBrush))

	h2.SetForeground(gui.NewQBrush3(gui.NewQColor2(color), core.Qt__NoBrush))

	s.msgModel.AppendRow([]*gui.QStandardItem{h1, h2})

	s.board.ResizeRowsToContents()
	s.board.ScrollToBottom()

	s.showTrayMessage(sender, msg)
}

func (s *myWindow) appendMsg(sender, msg string) {
	h1 := gui.NewQStandardItem2(sender)

	h2 := gui.NewQStandardItem2(msg)

	s.msgModel.AppendRow([]*gui.QStandardItem{h1, h2})

	s.board.ResizeRowsToContents()
	s.board.ScrollToBottom()

	s.showTrayMessage(sender, msg)
}

func (s *myWindow) setSignals() {
	s.bridge.ConnectAppendMsg(func(sender, msg string) {
		s.setTableColumnWidth()
		s.appendMsg(sender, msg)
	})

	s.bridge.ConnectAppendUser(func(user string) {
		//fmt.Println("Join:", user)
		var name = user
		var admin bool = false
		if strings.HasPrefix(user, "@") {
			name = user[1:]
			admin = true
		}
		item := gui.NewQStandardItem2(name)
		item.SetSelectable(false)
		item.SetTextAlignment(core.Qt__AlignHCenter)
		if admin {
			item.SetForeground(gui.NewQBrush3(gui.NewQColor2(core.Qt__red), core.Qt__NoBrush))
		}
		s.userModel.AppendRow2(item)
		s.users.ResizeRowsToContents()
	})

	s.bridge.ConnectRemoveUser(func(user string) {
		p := s.userModel.Parent(s.userModel.Item(0, 0).Index())
		n := s.userModel.RowCount(p)
		for i := 1; i < n; i++ {
			item := s.userModel.Item(i, 0)
			if item.Text() == user {
				s.userModel.RemoveRow(i, p)
				break
			}
		}
	})

	s.board.ConnectDoubleClicked(func(idx *core.QModelIndex) {
		item := s.msgModel.Item(idx.Row(), idx.Column())
		s.input.SetText(item.Text())
	})

	s.window.ConnectCloseEvent(func(e *gui.QCloseEvent) {
		e.Ignore()
		s.window.Hide()
	})
}

func (s *myWindow) ShowLogin() {
	s.login = widgets.NewQDialog(s.window, core.Qt__Window)
	s.login.SetWindowTitle(T("Login"))
	s.login.SetFixedWidth(320)

	grid := widgets.NewQGridLayout2()

	serverLabel := widgets.NewQLabel2(T("Server:"), s.login, core.Qt__Widget)
	grid.AddWidget3(serverLabel, 0, 0, 1, 1, 0)

	roomLabel := widgets.NewQLabel2(T("Room:"), s.login, core.Qt__Widget)
	grid.AddWidget3(roomLabel, 1, 0, 1, 1, 0)

	nickLabel := widgets.NewQLabel2(T("Nick:"), s.login, core.Qt__Widget)
	grid.AddWidget3(nickLabel, 2, 0, 1, 1, 0)

	pwdLabel := widgets.NewQLabel2(T("Password:"), s.login, core.Qt__Widget)
	grid.AddWidget3(pwdLabel, 3, 0, 1, 1, 0)

	serverInput := widgets.NewQLineEdit2("chat.freenode.net:6667", s.login)
	grid.AddWidget3(serverInput, 0, 1, 1, 1, 0)

	roomInput := widgets.NewQLineEdit(s.login)
	grid.AddWidget3(roomInput, 1, 1, 1, 1, 0)

	nickInput := widgets.NewQLineEdit(s.login)
	grid.AddWidget3(nickInput, 2, 1, 1, 1, 0)
	num := time.Now().Unix() % 1000
	nickInput.SetText(fmt.Sprintf("xtalker%d", num))

	pwdInput := widgets.NewQLineEdit(s.login)
	grid.AddWidget3(pwdInput, 3, 1, 1, 1, 0)
	pwdInput.SetEchoMode(widgets.QLineEdit__Password)

	buttons := widgets.NewQHBoxLayout()

	submit := widgets.NewQPushButton2(T("Login"), s.login)
	buttons.AddWidget(submit, 1, 0)

	cancel := widgets.NewQPushButton2(T("Cancel"), s.login)
	buttons.AddWidget(cancel, 1, 0)

	grid.AddLayout2(buttons, 4, 0, 1, 2, 0)

	cancel.ConnectClicked(func(clicked bool) {
		s.login.Close()
		s.window.Close()
		//s.app.Quit()
	})

	submit.ConnectClicked(func(clicked bool) {
		//fmt.Println(serverInput.Text(), roomInput.Text(), nickInput.Text(), pwdInput.Text())
		info := doLogin(serverInput.Text(), roomInput.Text(), nickInput.Text(), pwdInput.Text(), s.bridge)
		s.header.SetText(info)
		s.login.Close()
		s.window.Show()
		s.showSystemTray()
	})

	s.login.SetLayout(grid)

	s.login.SetModal(true)
	s.login.Show()
}

func initLocale() {
	exe1, _ := os.Executable()
	dir1 := filepath.Dir(exe1)
	gettext.BindTextdomain("mimichat", filepath.Join(dir1, "..", "locale"), nil)
	gettext.Textdomain("mimichat")
}

func main() {
	bot = new(Bot)
	defer bot.Close()
	initLocale()

	app := widgets.NewQApplication(len(os.Args), os.Args)

	win := new(myWindow)
	win.CreateWithApp(app)
	win.ShowLogin()

	app.Exec()
	//gettext.SaveLog()
}
